/**
 *  amoobject - C++ simple, safe and fast signal/slot mechanism implementation.
 *
 *  Copyright (C) 2011-2012 Abdeslam MOKRANI (abdesmok@gmail.com).
 *  All rights reserved.
 *
 *  This file is part of amo project.
 *
 *  This file may be freely redistributed and/or modified under ther terms
 *  of the GNU Lesser General Public (LGPL) License as published by the
 *  Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This file is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this file. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef __TEST__
#define __TEST__

#include <string>
#include <iostream>
#include <sstream>

static bool traceOutputOn = false;
static std::string trace;
static int numSucceed = 0;
static int numFailed = 0;

class Console : public std::stringstream {
public:
    Console() {
        *static_cast<std::stringstream *>(this) << "TRACE:";
    }
    
    ~Console() {
        std::cout << this->str() << std::endl;
    }
    
    template<typename T> Console &operator<<(T const &value) {
       return _write(value);
   }

   template<typename T> Console &operator<<(const T *value) {
       return _write(value);
   }

   template<typename T> Console &operator<<(T *value) {
       return _write(value);
   }

private:
   template<typename T> Console &_write(const T &value) {
       *static_cast<std::stringstream *>(this) << " " << value;
       *static_cast<std::stringstream *>(this) << value;
       return *this;
   }
};

#define ENDL std::cout << std::endl;

#define CODE(_code) std::cout << "CODE: " << #_code << std::endl; _code;

#define TRACE(_content) { \
   if (::traceOutputOn) \
       Console() << _content; \
   std::stringstream st; \
   st << _content; \
   ::trace += st.str() + "\n"; \
}

#define TRACE_CODE(_code) ::trace.clear(); ::traceOutputOn = true; CODE(_code); ::traceOutputOn = false;

#define TEST_TRACE_CODE(...) { \
   std::string trace = ::trace; \
   ::trace.clear(); \
   __VA_ARGS__; \
   if (trace != ::trace) { \
       std::cout << "FAILED: (\n" << trace << "\n) != (\n" << ::trace << "\n)\n"; ++::numFailed; \
   } else { \
       std::cout << "SUCCEED"; ++::numSucceed; \
   } \
   ::trace.clear(); \
}

#endif // __TEST__

